#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/wait.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "ThreadPool.hpp"
#include "Task.hpp"

const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";

class tcpServer;

class threadData
{
public:
    threadData(int sockfd, const std::string &ip, const uint16_t &port, tcpServer *t)
        : sockfd(sockfd), clientip(ip), clientport(port), tsvr(t)
    {
    }

public:
    int sockfd;
    std::string clientip;
    uint16_t clientport;
    tcpServer *tsvr;
};

class tcpServer
{
public:
    tcpServer(const uint16_t &port, const std::string &ip = defaultip)
        : _listensockfd(defaultfd), _ip(ip), _port(port)
    {
    }
    void Init()
    {
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            printf("create socket errno:%d ,errstring: %s\n", errno, strerror(errno));
            exit(0);
        }
        printf("create socket success,sockfd: %d\n", _listensockfd);

        // 填充信息,该结构体(ip+port),struct in_addr纯ip
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        inet_aton(_ip.c_str(), &(local.sin_addr));
        if (bind(_listensockfd, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            printf("bind error,errno: %d,errstring :%s\n", errno, strerror(errno));
            exit(1);
        }
        printf("bind success sockfd: %d\n", _listensockfd);
        if (listen(_listensockfd, 5) < 0)
        {
            printf("listen error,errno: %d,errstring :%s\n", errno, strerror(errno));
            exit(2);
        }
        printf("listen success sockfd: %d\n", _listensockfd);
    }
    
    static void *Routine(void *args)
    {
        pthread_detach(pthread_self()); // 将线程设置为分离状态

        threadData *td = static_cast<threadData *>(args);            // 转换参数类型
        td->tsvr->Service(td->sockfd, td->clientip, td->clientport); // 执行业务逻辑

        delete td; // 释放线程数据
        return nullptr;
    }
    

    void Start()
    {
        ThreadPool<Task>::GetInstance()->Start();               //启动线程池
        std::cout << "tcpServer is running" << std::endl;
        for (;;)
        {
            // 获取新连接
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(_listensockfd, (struct sockaddr *)&client, &len);
            if (sockfd < 0)
            {
                printf("accept error errno: %d,errstring: %s\n", errno, strerror(errno));
                continue;
            }
            char clientip[32];
            uint16_t clientport = ntohs(client.sin_port);
            inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));

            // 根据新连接进行通信服务
            printf("get a new link...,sockfd: %d,client ip: %s,client port: %d\n", sockfd, clientip, clientport);

            // version 1 单进程
            /*
            Service(sockfd,clientip,clientport);
            close(sockfd);
            */

            // version 2 多进程
            /*
            pid_t pid=fork();
            if(pid==0)                          //子进程只管创建孙子进程
            {
                close(_listensockfd);
                if(fork()>0)  exit(0);
                Service(sockfd,clientip,clientport);        //孙子进程负责执行任务，不用等待，最后由系统领养
                close(sockfd);
                exit(0);
            }
            close(sockfd);
            pid_t rid=waitpid(pid,nullptr,0);
            (void)rid;
            */

            // version 3 多线程
            /*          
            threadData *td = new threadData(sockfd, clientip, clientport, this);
            pthread_t tid;
            pthread_create(&tid, nullptr, Routine, td);
            */

            // version 4 线程池
            Task t(sockfd,clientip,clientport);             //构造任务
            ThreadPool<Task>::GetInstance()->push(t);      
            
        }
    }

    
    void Service(int sockfd, const std::string &clientip, const uint16_t &clientport)
    {
        char buf[4096];
        while (1)
        {
            ssize_t n = read(sockfd, buf, sizeof(buf));
            if (n > 0)
            {
                buf[n] = 0;
                std::cout << "client say# " << buf << std::endl;
                std::string echo_string = "tcpserver say#";
                echo_string += buf;
                write(sockfd, echo_string.c_str(), echo_string.size());
            }
            else if (n == 0) // 客户端退出
            {
                printf("%s:%d quit,server close sockfd: %d\n", clientip.c_str(), clientport, sockfd);
                break;
            }
            else
            {
                printf("read error,sockfd: %d,client ip: %s,client port: %d", sockfd, clientip.c_str(), clientport);
                break;
            }
        }
    }
    
    ~tcpServer()
    {
    }

private:
    int _listensockfd;
    uint16_t _port;
    std::string _ip;
};

